home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 20 code / Pict Tricks / CLUTLess / CLUTLess.c next >
Encoding:
C/C++ Source or Header  |  1994-07-28  |  7.4 KB  |  226 lines  |  [TEXT/MMCC]

  1. /*     
  2.                             CLUTLess
  3.                             
  4.             In some instances it is desireable to store picts stripped of
  5.             CLUTs in order to save some room in the disk. This sample shows
  6.             how to create such picts and how to properly display them back.
  7.             
  8.             SimpleInC.c -- initialization stuff and event loop
  9.             CLUTLess.c  -- code that does the creation of the clut less pict;
  10.                            shows also how to display the pictures.
  11.             CLUTLessFile.c --
  12.                            Routines to access files that have no direct
  13.                            relationship with picture handling.
  14.     
  15. */
  16.  
  17. /*    In cases when there is a large number of picts containing eight bit pixmaps
  18.     the color table associated to each one of them may add to a large ammount, in the
  19.     cases when the color table for the different images is the same it is possible
  20.     to save the disk space by storing the images with out cluts, storing one copy of
  21.     the clut and then 'resotring the clut when displaying the image.
  22.     
  23.     This may be specially important for cd based apps that handle large number of images.
  24.     Let assume for simplicity that each picture contains only one pixmap so the math
  25.     goes like this, CLUT size = seed                4
  26.                                 flags                2
  27.                                 size                2
  28.                                 ctTable 256*8     2048
  29.                                 ---------------------
  30.                                                 2K per pict
  31.     So if the cd contains 1000 pictures the savings could be important.
  32.     
  33.     Note that there is the assumption here that the number of picts that can be rendered using
  34.     the same clut is large, if this is not true then the overhead is not worth it.
  35.     
  36.     (The sample uses a picture to begin with but this is not important.)
  37. */
  38.  
  39. #include "CLUTLess.h"
  40.  
  41. /*    The way we are going to handle this is the following:
  42.  
  43.     - Create PICT file containing striped pixmap and also the 'clut'
  44.     - Read in the picture and its accompanying clut
  45.     
  46.     Note that for the purposes of this sample we use no spooling but this does not
  47.     mean that it is not possible to use the techniques described here to create
  48.     and display pictures along with file spooling.
  49. */
  50.  
  51. /* proc returns true if the original picture has been read in, and a pict
  52.    file was read in successfuly.
  53. */
  54. Boolean SetupPictures(void)
  55. {
  56.     Boolean result = false;
  57.  
  58.     if ( SavePicture() ) {            //  Pict file was created.
  59.       result = GetPictBack();        //  and re-acqired
  60.     }
  61.     return result;
  62. }
  63.  
  64.     
  65. /* =============================================================================================== */
  66. /* =============================================================================================== */
  67. /*
  68.     Here we create the picture and save it to disk
  69.     
  70. */
  71. Boolean SavePicture(void)
  72. {
  73. GWorldPtr     myGWorld;
  74. Rect        gwRect;
  75. Boolean     result = true; // return true in case user just wants to display a file
  76. CGrafPtr    oldPort;
  77. GDHandle    oldDevice;
  78. PicHandle    localPict;
  79.  
  80.     GetGWorld(&oldPort, &oldDevice);
  81.     //     First we get the original pict from a resource.
  82.     if ( !( gOrigPict = GetPicture(pictID) )) goto bail; // what use if no picture
  83.     DetachResource((Handle)gOrigPict);                            // goes away when app quits
  84.     gCurrPict = gOrigPict;
  85.     
  86.     gwRect = (*gOrigPict)-> picFrame;
  87.     
  88.     if ( NewGWorld(&myGWorld, desiredDepth, &gwRect, nil, nil, 0) ) goto bail; // no offscreen
  89.     if (LockPixels(GetGWorldPixMap(myGWorld))) {
  90.     
  91.       SetGWorld(myGWorld, nil);                // draw the image offscreen
  92.       DrawPicture(gOrigPict, &gwRect);
  93.       SetGWorld(oldPort, oldDevice);
  94.       if ( localPict = CreateCLUTLessPict(myGWorld) ) {
  95.         if ( SaveCLUTLessPict(localPict) ) {
  96.           result = true;
  97.         }
  98.       }
  99.       UnlockPixels(GetGWorldPixMap(myGWorld));
  100.       DisposeGWorld(myGWorld);
  101.     }
  102. bail:
  103.     return result;
  104. }
  105.  
  106. /* =============================================================================================== */
  107. /*
  108.     the process we want to exemplify when creating the picture is the following:
  109.     
  110.     1- Create a GWorld and 'display' the image there.
  111.     2- Call OpenPicture to start recording
  112.     3-     Set the color table handle in the source pixmap to nil
  113.     4-  Call CopyBits to store the image sans clut in the picture
  114.     5- Call ClosePicture to complete the process
  115.     
  116. */
  117. PicHandle CreateCLUTLessPict(GWorldPtr myGWorld) { // at this point clut is already locked
  118.  
  119. PicHandle         new = nil;
  120. PixMapHandle     pm;
  121. BitMap             *srcPix;
  122. Rect             offRect = myGWorld->portRect;
  123. CGrafPtr    oldPort;
  124. GDHandle    oldDevice;
  125.  
  126.     GetGWorld(&oldPort, &oldDevice);
  127.  
  128.     pm = GetGWorldPixMap(myGWorld);
  129.     HLock((Handle)pm);
  130.     srcPix = (BitMap *) *pm;                    // get pointer to make code more readable
  131.     gSharedClut = (*pm)->pmTable;
  132.     (*pm)->pmTable = nil;                        // set pixmap clut to nil
  133.  
  134.     SetGWorld(myGWorld, nil);            
  135.     ClipRect(&offRect);
  136.     new = OpenPicture(&offRect);         // gWorld rect was created from pict rect
  137.         CopyBits(srcPix,                 // when creating a pict source is what really matters
  138.                  srcPix,                 // use same as dest
  139.                  &offRect,                // nice rect
  140.                  &offRect,                // same
  141.                  srcCopy,
  142.                  nil);
  143.     ClosePicture();                        // completes creation process
  144.     
  145.     HUnlock((Handle)pm);
  146.     (*pm)->pmTable = gSharedClut;            // put this back
  147.     
  148.     HandToHand((Handle *)(&gSharedClut));        // make a copy of the clut so it can be stored in the file
  149.                                         // handle gets disposed when closing resource file.
  150.     SetGWorld(oldPort, oldDevice);
  151.     return new;
  152. }
  153.  
  154. /* =============================================================================================== */
  155. /*     Given that this picts are not going to look well without some
  156.     pre-processing the best way to store them is not a PICT file that users
  157.     may feel tempted to view with some other app.If the picts are not very big 
  158.     in size then resources could be used, for large images a data file is recommended.
  159.     
  160.     For the exercise we'll use a pict file that is easy to disect; the following
  161.     code promts the user for a place where to put the resulting pict and the
  162.     'clut' resource to be used when viewing it.
  163.     
  164.     
  165. */
  166. Boolean SaveCLUTLessPict(PicHandle aPict) {
  167.     Point        dlgPos = {100,100};                /* Position the dialog box */
  168.     SFReply        sfr;                            /* StdFile reply */
  169.     short         fileRef;
  170.     long        pictSize = GetHandleSize((Handle)aPict);
  171.     Boolean     result = false;
  172.     
  173.     /* Prompt the user for a file name and create it */
  174.     SFPutFile(dlgPos, "\pPICT file to create:","\pPICT File",nil,&sfr);
  175.     if (sfr.good) {
  176.       if ( fileRef = OpenPictureFile(&sfr) ) {
  177.           HLock((Handle)aPict);
  178.         if ( FSWrite(fileRef, &pictSize, (Ptr)*aPict) ) 
  179.           KillFile(fileRef, &sfr);
  180.         else {
  181.           ClosePictureFile(fileRef, &sfr, aPict);
  182.           result = true;
  183.         }
  184.           HUnlock((Handle)aPict);
  185.       }
  186.     }
  187.     /* the pict is in the file now we save the 'clut' resource that will allow
  188.        to view the image in its full color.
  189.     */
  190.     SaveCLUTResource(&sfr);
  191.     
  192.     return result;
  193. }
  194.  
  195. /* =============================================================================================== */
  196. /* =============================================================================================== */
  197. /* this is the replacement for the standard bits proc. When a picture is being drawn]
  198.     the routine is called just before the pixmap is transferred to the destination;
  199.     at this time our routine will replace the color table filed with the color
  200.     table contained in the 'clut' resource.
  201. */
  202.  
  203. pascal void AddClutProc(BitMap *src, 
  204.             Rect *srcR, Rect *dstR,
  205.             short mode, RgnHandle msk) 
  206. {
  207.     CTabHandle    saveCTH;
  208.  
  209.     // Save color table handle. 
  210.     saveCTH = ((PixMapPtr) src)->pmTable;    
  211.     // Put 'clut' resource.
  212.     ((PixMapPtr) src)->pmTable = gSharedClut;
  213.     // Let QuickDraw do the work.
  214.     StdBits(src, srcR, dstR, mode, msk); 
  215.     // Restore saved handle and return.
  216.     ((PixMapPtr) src)->pmTable = saveCTH;
  217. }
  218.  
  219. void    InitProcs(CQDProcs *theProcs)
  220. {
  221.     SetStdCProcs(theProcs);    // default procs
  222.     theProcs->bitsProc = NewQDBitsProc(AddClutProc);
  223. }
  224.  
  225.     
  226.